/**
 * 
 */
package net.toocruel.iqismart.service.core.impl;


import net.toocruel.iqismart.dao.UserRepository;
import net.toocruel.iqismart.dao.condition.ArticlesCondition;
import net.toocruel.iqismart.dao.core.*;
import net.toocruel.iqismart.entity.common.Category;
import net.toocruel.iqismart.entity.constants.Action;
import net.toocruel.iqismart.entity.core.Article;
import net.toocruel.iqismart.entity.core.Credit;
import net.toocruel.iqismart.entity.rbac.User;
import net.toocruel.iqismart.service.UserService;
import net.toocruel.iqismart.service.core.ArticleService;
import net.toocruel.iqismart.service.core.EmailService;
import net.toocruel.iqismart.service.core.TagService;
import net.toocruel.iqismart.service.exception.ArticleNotFoundException;
import net.toocruel.iqismart.service.helper.UserHelper;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;

/**
 * @author toocruel
 *
 */
@Service
@Transactional
public class ArticleServiceImpl implements ArticleService {
    @Autowired
    private UserRepository userRepository;
    @Autowired
    private TagRepository tagRepository;

    @Autowired
    private QuestionRepository questionRepository;

    @Autowired
    private AttentionRepository attentionRepository;

    @Autowired
    private CollectionRepository collectionRepository;

    @Autowired
    private TagService tagService;

    @Autowired
    private CategoryRepository categoryRepository;

    @Autowired
    private AnswerRepository answerRepository;

    @Autowired
    private QuestionInvitationRepository questionInvitationRepository;

    @Autowired
    private EmailService emailService;

    @Autowired
    private UserService userService;

    @Autowired
    private ArticleRepository articleRepository;

    @Override
    public Article postArticle(Article article) {

        article.setUser(UserHelper.getCurrentUser()==null?article.getUser():UserHelper.getCurrentUser());

        //标签
        article.setTags(tagService.findAndCreateIfNotExist(article.getCategoryId(),article.getTagNames()));

        if(article.getCategoryId()!= null && article.getCategoryId()>0){
            article.setCategory(categoryRepository.findOne(article.getCategoryId()));
        }

        //状态 1 审核通过
        article.setStatus(1);
        article = articleRepository.save(article);

        //积分奖励
        userService.addCredit(new Credit(article.getUser(),Action.CREATE_ARTICLE,article));

        return article;
    }

    @Override
    public Article editArticle(Article article) {
        Article _article = articleRepository.findOne(article.getId());

        //标题 描述
        _article.setTitle(article.getTitle());
        _article.setContent(article.getContent());
        _article.setSummary(article.getSummary());
        _article.setLogo(article.getLogo());

        //分类
        if(article.getCategoryId()!= null && article.getCategoryId()>0){
            _article.setCategory(categoryRepository.findOne(article.getCategoryId()));
        }

        //标签
        _article.setTags(tagService.findAndCreateIfNotExist(article.getCategoryId(), article.getTagNames()));

        articleRepository.save(_article);
        return _article;
    }





    @Override
    public List<Article> getSuggests(String word) {
        return articleRepository.findAll();
    }




    @Override
    public Page<Article> findAll(ArticlesCondition condition, PageRequest pageRequest) {

        String categorySlug = condition.getCategorySlug();
        Long categoryId = condition.getCategoryId();
        String filter = condition.getFilter();

        //排序
        if(StringUtils.isNotBlank(filter)){
            if("newest".equals(filter)){
                pageRequest = new PageRequest(pageRequest.getPageNumber(),pageRequest.getPageSize(),new Sort(Sort.Direction.DESC,"id"));
            }else if("newcomment".equals(filter)){
                pageRequest = new PageRequest(pageRequest.getPageNumber(),pageRequest.getPageSize(),new Sort(Sort.Direction.DESC,"lastAnswer").and(new Sort(Sort.Direction.DESC,"id")));
            }else if("mostview".equals(filter)){
                pageRequest = new PageRequest(pageRequest.getPageNumber(),pageRequest.getPageSize(),new Sort(Sort.Direction.DESC,"views").and(new Sort(Sort.Direction.DESC,"id")));
            }else if("mostcomment".equals(filter)){
                pageRequest = new PageRequest(pageRequest.getPageNumber(),pageRequest.getPageSize(),new Sort(Sort.Direction.DESC,"commentNum").and(new Sort(Sort.Direction.DESC,"id")));
            }else if("best".equals(filter)){
                pageRequest = new PageRequest(pageRequest.getPageNumber(),pageRequest.getPageSize(),new Sort(Sort.Direction.DESC,"best").and(new Sort(Sort.Direction.DESC,"id")));
            }else if("recommend".equals(filter)){
                pageRequest = new PageRequest(pageRequest.getPageNumber(),pageRequest.getPageSize(),new Sort(Sort.Direction.DESC,"recommend").and(new Sort(Sort.Direction.DESC,"id")));
            }
        }

        Page<Article> articles = articleRepository.findAll((root, query, cb) -> {
            List<Predicate> predicates = new ArrayList<>();
            //页面用标签id来传参
            if (categoryId != null && categoryId > 0) {
                Category category = categoryRepository.findOne(categoryId);
                condition.setCategory(category);
                predicates.add(cb.equal(root.get("category"), category));
            }

            //页面用标签slug来传参
            if (StringUtils.isNotBlank(categorySlug)) {
                Category category = categoryRepository.findBySlug(categorySlug);
                condition.setCategory(category);
                predicates.add(cb.equal(root.get("category"), category));
            }

            //where 条件
            if(StringUtils.isNotBlank(filter)){
                if("best".equals(filter)){
                    predicates.add(cb.greaterThan(root.get("best"),0));
                }else if("recommend".equals(filter)){
                    predicates.add(cb.greaterThan(root.get("recommend"),0));
                }
            }



            //TODO

            return cb.and(predicates.toArray(new Predicate[predicates.size()]));
        }, pageRequest);

        syncArticleNum(articles);


        return articles;
    }

    @Override
    public void addViews(Article article) {
        article.setViews(article.getViews()+1);
        articleRepository.save(article);
    }

    private void syncArticleNum(Iterable<Article> articles){
        articles.forEach(article -> {
            try {
                if(article.getSyncedAt()!= null && System.currentTimeMillis() - article.getSyncedAt()<1000 *60 * 60 * 24  ){
                    return;
                }
                if(CollectionUtils.isNotEmpty(article.getComments())){
                    if(article.getCommentNum() != article.getComments().size()){
                        article.setCommentNum(article.getComments().size());
                        article.setSyncedAt(System.currentTimeMillis());
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        });

        articleRepository.save(articles);

    }

    @Override
    public Article findById(Long id) {
        Article article = articleRepository.findOne(id);
        if(article == null){
            throw new ArticleNotFoundException();
        }
        return article;
    }

    @Override
    public List<User> getTopUsers() {
        //TODO 获取作家排行
        return userRepository.findAll(new PageRequest(0,10)).getContent();
    }

    @Override
    public List<Article> getHotArticles(int count) {
//        return articleRepository.findAll(new PageRequest(0,10,new Sort(Sort.Direction.DESC,"supportNum").and(new Sort(Sort.Direction.DESC,"commentNum")).and(new Sort(Sort.Direction.DESC,"views")))).getContent();
        return articleRepository.findAll((root, query, cb) -> cb.isNotEmpty(root.get("supports")) ,new PageRequest(0,count,new Sort(Sort.Direction.DESC,"supports").and(new Sort(Sort.Direction.DESC,"id")))).getContent();
    }

    @Override
    public List<User> getHotUsers(int count) {
        return userRepository.findAll(new PageRequest(0,count,new Sort(Sort.Direction.DESC,"articles").and(
                new Sort(Sort.Direction.DESC,"supports")
        ))).getContent();
    }

    @Override
    public List<Article> getLatestArticles(int count) {
        return articleRepository.findAll(new PageRequest(0,count,new Sort(Sort.Direction.DESC,"id"))).getContent();
    }
}
